package main

import (
	"fmt"
	"sync"
	"time"
)

var (
	x  int64
	wg sync.WaitGroup
	// 互斥锁
	lock   sync.Mutex
	rwlock sync.RWMutex
)

func main() {
	// go fmt.Println("lt")
	// fmt.Println("这main方法")
	// time.Sleep(time.Second)

	// cacheCh:=make(chan int,5) // 缓冲channel
	// ch:=make(chan string) // 无缓冲channel 发送和接受同时进行操作
	// go func(){
	// 	fmt.Println("channel")
	// 	ch <- "goroutine 完成"
	// }()

	// fmt.Println("我是 main goroutine")

	// v:=<-ch
	// fmt.Println("接受到的chan中的值为：",v)

	// cacheCh:=make(chan int,5)
	// cacheCh <- 2
	// cacheCh <- 3
	// close(cacheCh) // 还可以接收 channel 里的数据
	// // cacheCh <- 4
	// // cacheCh <- 5
	// // cacheCh <- 6
	// fmt.Println("cacheCh容量为:",cap(cacheCh),",元素个数为：",len(cacheCh))

	// onlySend:=make(chan<- int)// 单向发送
	// onlyReceive:=make(<-chan int)// 单向接收

	// select + channel 多路复用
	// firstCh:=make(chan string)
	// secondCh:=make(chan string)
	// threeCh:=make(chan string)
	// go func(){
	// 	firstCh <- downloadFile("fisttCh  downloadFile")
	// }()
	// go func(){
	// 	secondCh <- downloadFile("secondCh  downloadFile")
	// }()
	// go func(){
	// 	threeCh <- downloadFile("threeCh  downloadFile")
	// }()
	// select {
	// case filePath := <-firstCh:
	// 	fmt.Println(filePath)
	//  case filePath := <-secondCh:
	// 	fmt.Println(filePath)
	//  case filePath := <-threeCh:
	// 	fmt.Println(filePath)
	// }

	// go hello()
	// go hello()
	// go hello()
	// fmt.Println("main goroutine done!")
	// time.Sleep(time.Second)

	// for i := 0; i < 10; i++ {
	// 	wg.Add(1)
	// 	go hello2(i) // 并发随机调度
	// }
	// wg.Wait() // 等待

	// ch := make(chan int, 1) // 创建一个容量为1的有缓冲区通道
	// // go recv(ch) // goroutine 接收
	// ch <- 10 // 10发送到chan中
	// fmt.Println(len(ch))
	// close(ch)

	// // chan 是否关闭
	// ch1 := make(chan int)
	// ch2 := make(chan int)
	// go func() {
	// 	for i := 0; i < 100; i++ {
	// 		ch1 <- i
	// 	}
	// 	close(ch1)
	// }()
	// go func() {
	// 	for {
	// 		i, ok := <-ch1
	// 		if !ok {
	// 			break
	// 		}
	// 		ch2 <- i * i
	// 	}
	// 	close(ch2)
	// }()
	// for i := range ch2 {
	// 	fmt.Println(i)
	// }

	// wg.Add(2)
	// go add()
	// go add()
	// wg.Wait()
	// fmt.Println(x)

	// 读多写少的场景 读写锁RWMutex
	start := time.Now()
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go write()
	}
	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go read()
	}

	wg.Wait()
	end := time.Now()
	fmt.Println(end.Sub(start))
}

/*
	数据流动、传递的场景中要优先使用 channel，它是并发安全的，性能也不错
*/
func downloadFile(chanName string) string {
	time.Sleep(time.Second)
	return chanName + ":filePath"
}

func hello() {
	fmt.Println("Hello Goroutine!")
}

func hello2(i int) {
	defer wg.Done() // goroutine结束就登记-1
	fmt.Println("Hello Goroutine!", i)
}

func recv(c chan int) {
	ret := <-c
	fmt.Println("接收成功", ret)
}

func add() {
	for i := 0; i < 5000; i++ {
		lock.Lock() // 加锁 保证有且只有一个goroutine进入临界区
		x = x + 1
		lock.Unlock() // 解锁
	}
	wg.Done()
}

func write() {
	// lock.Lock()   // 加互斥锁
	rwlock.Lock() // 加写锁
	x = x + 1
	time.Sleep(10 * time.Millisecond) // 假设读操作耗时10毫秒
	rwlock.Unlock()                   // 解写锁
	// lock.Unlock()                     // 解互斥锁
	wg.Done()
}

func read() {
	// lock.Lock()                  // 加互斥锁
	rwlock.RLock()               // 加读锁
	time.Sleep(time.Millisecond) // 假设读操作耗时1毫秒
	rwlock.RUnlock()             // 解读锁
	// lock.Unlock()                // 解互斥锁
	wg.Done()
}
